МИВК Многофункциональный
информационно-вычислительный
комплекс ОИЯИ

Для профилирования и поиска утечек памяти в root-макросах следует использовать стандартную процедуру valgrind. Чтобы сгенерировать данные для анализа выполните

valgrind root.exe NameMacro.C

Обратите внимание,что в командной строке необходимо набрать именно root.exe, а не просто root. По умолчанию, valgrind запускает модуль memcheck, однако пользователь может указать какой модуль должен выполняться с помощью опции --tool, передав в качестве аргумента имя нужного модуля, например, вот так:

valgrind –-tool = memcheck root.exe NameMacro.C

В ходе своей работы, модуль memcheck определяет несколько видов ошибок работы с памятью:

  • чтение или запись по неправильным адресам памяти — за границами выделенных блоков памяти и т.п;
  • использование не инициализированных значений;
  • ошибки освобождения памяти, например, когда блок памяти уже был освобожден в другом месте;
  • использование "неправильной" функции освобождения памяти, например, использование delete для памяти, выделенной с помощью new [];
  • передача некорректных параметров системным вызовам, например, указание неправильных указателей для операций чтения из буфера, указанного пользователем;
  • пересечение границ блоков памяти при использовании операций копирования/перемещения данных между двумя блоками памяти.

Помимо модуля memcheck valgrind имеет следующие модули-анализаторы: cachegrind, callgrindmassif и helgrind.

Профилирование программ может осуществляться с помощью двух модулей — cachegrind и callgrind. Каждый из них собирает разную информацию. При этом нельзя полагаться на результаты работы только одного из модулей, лучше проводить поиск "узких" мест в программах на основе анализа вывода каждого из модулей.

Модуль cachegrind проводит сбор статистики по попаданию в кэш при выполнении операций чтения и записи данных и инструкций программ. Результаты собранные данным модулем по умолчанию выводятся в файл с именем cachegrind.out.<pid> (pid — идентификатор процесса).

Mодуль callgrind позволяет собрать информацию о дереве вызовов функций в программе. По умолчанию он собирает данные о количестве выполненных инструкций, зависимостях между вызывающей и вызываемой функциями и количество вызовов конкретных функций. Кроме того, можно включить эмуляцию кэшей, аналогичную cachegrind, что позволит собрать данные о доступе к памяти. Данные собранные модулем выводятся в файл callgrind.out.<pid>.

Для визуализации данных, полученных от модулей callgrind и cachegrind, существует программа — kcachegrind, которая отображает полученные данные, и позволяет выполнять навигацию по исходному коду программы. Программа позволяет отображать собранные данные различными способами — в виде таблиц, карт и графов вызова функций. Пример отображения этих данных представлен на рисунке.

kachegrind

Модуль massif используется для анализа выделения памяти в программах. Он собирает сведения не только о размерах блоков, выделяемых программой, но также и о том, сколько дополнительной памяти потребуется для хранения служебной информации. После завершения программы под управлением massif, valgrind выдает краткую сводку использования памяти, а подробные данные выводятся в файл massif.out.<pid>. Для анализа этих данных может использоваться программа ms_print, входящая в поставку valgrind. Эта программа может выдавать данные в виде графиков, демонстрирующих выделение памяти в программе в процессе работы.

Также valgrind содержит инструмент helgrind , позволяющий найти ошибки синхронизации в многопоточных программах. Этот модуль помогает обнаружить следующие классы ошибок:

  • потенциальные блокировки (deadlocks), возникающие из-за неправильного порядка выставления блокировок;
  • повреждение данных (data races) из-за неправильных, или отсутствующих блокировок на доступ к памяти;
  • неправильное использование функций POSIX API. Этот класс ошибок включает в себя разные ошибки, например, рекурсивное блокирование не рекурсивного мьютекса  (мьютекс — это совместно используемая переменная, которая может находиться в одном из двух состояний: заблокированном или незаблокированном) или освобождение памяти, хранящей блокировку.